<template>
  <div>
    <input type="text" v-model="search">

    <div ref="list" class="infinite-list-container" @scroll="scrollEvent($event)">

      <div class="infinite-list-phantom" :style="{ height: listHeight + 'px' }"></div>
      <div class="infinite-list" :style="{ transform: getTransform }">
        <div ref="items"
             class="infinite-list-item"
             v-for="(item) in visibleData"
             :key="item"
             :style="{ height: itemSize + 'px',lineHeight: (itemSize-20) + 'px' }"
             v-html="item"
        >
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "infinite",
  components: {},
  props: {
    //所有列表数据
    listData: {
      type: Array,
      default: () => []
    },
    //每项高度
    itemSize: {
      type: Number,
      default: 200
    }
  },
  data() {
    return {
      //可视区域高度
      screenHeight: 0,
      //偏移量
      startOffset: 0,
      //起始索引
      start: 0,
      //结束索引
      end: null,
      search: "",
    }
  },
  created() {
  },
  mounted() {
    this.screenHeight = this.$refs.list.clientHeight;  // 这里修改为你那个列表可视的高度
    this.start = 0;
    this.end = this.start + this.visibleCount + 3;
  },

  methods: {
    scrollEvent() {
      //当前滚动位置
      let scrollTop = this.$refs.list.scrollTop;
      //此时的开始索引
      this.start = Math.floor(scrollTop / this.itemSize);
      //此时的结束索引
      this.end = this.start + this.visibleCount + 3;
      //此时的偏移量
      this.startOffset = scrollTop - (scrollTop % this.itemSize);
    }
  },
  computed: {
    replaceArr() {
      const listData = JSON.parse(JSON.stringify(this.listData))
      const search = this.search
      // 匹配关键字正则
      const replaceReg = new RegExp(search, 'g')
      // 高亮替换v-html值
      const replaceString =  `<font color='#F14F4A'>${search}</font>`
        for (let i = 0; i < listData.length; i++) {
         // 开始替换
         listData[i]= listData[i].replace(replaceReg, replaceString)
       }
      return listData
    },
    _listData() {
      return this.replaceArr.filter(data => {
        return String(data)
            .toLowerCase()
            .indexOf(this.search) > -1
      })
    },
    //列表总高度
    listHeight() {
      return this._listData.length * this.itemSize;
    },
    //可显示的列表项数
    visibleCount() {
      return Math.ceil(this.screenHeight / this.itemSize)
    },
    //偏移量对应的style
    getTransform() {
      return `translate3d(0,${this.startOffset}px,0)`;
    },
    //获取真实显示列表数据
    visibleData() {
      return this._listData.slice(this.start, Math.min(this.end, this._listData.length));
    }
  },
  watch: {},
  beforeDestroy() {
  },
  destroyed() {
  }
}
</script>

<style scoped lang="scss">
.infinite-list-container {
  height: 400px;
  width: 100%;
  overflow: auto;
  position: relative;
  -webkit-overflow-scrolling: touch;
}

.infinite-list-phantom {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  z-index: -1;
}

.infinite-list {
  left: 0;
  right: 0;
  top: 0;
  position: absolute;
  text-align: center;
}

.infinite-list-item {
  padding: 10px;
  color: #555;
  box-sizing: border-box;
  border-bottom: 1px solid #999;
}
</style>